package org.dtrd.modules.evaluation.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dtrd.common.util.DateUtils;
import org.dtrd.config.system.Constant;
import org.dtrd.modules.evaluation.entity.bean.*;
import org.dtrd.modules.evaluation.entity.bean.report.EvaluationReport;
import org.dtrd.modules.evaluation.entity.bean.report.TotalEvaluationReports;
import org.dtrd.modules.evaluation.entity.po.*;
import org.dtrd.modules.evaluation.mapper.DtrdEntRdEvaluationMapper;
import org.dtrd.modules.evaluation.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 量表信息表 服务实现类
 * </p>
 *
 * @author QR
 * @since 2021-11-09
 */
@Service
@DS("multi-datasource1")
public class DtrdEntRdEvaluationServiceImpl extends ServiceImpl<DtrdEntRdEvaluationMapper, DtrdEntRdEvaluation> implements IDtrdEntRdEvaluationService {

    @Autowired
    private IDtrdEntEvaluationRdSdscaService sdscaService;
    @Autowired
    private IDtrdEntEvaluationRdMmas8Service mmas8Service;
    @Autowired
    private IDtrdEntEvaluationRdBmqService bmqService;
    @Autowired
    private IDtrdEntEvaluationRdAngiocardiopathyService angiocardiopathyService;
    @Autowired
    private IDtrdEntEvaluationRdSasService sasService;
    @Autowired
    private IDtrdEntEvaluationRdSdsService sdsService;
    @Autowired
    private IDtrdEntEvaluationRdDiabetesService diabetesService;
    @Autowired
    private IDtrdEntEvaluationRdHappyService happyService;
    @Autowired
    private IDtrdEntEvaluationRdParqService parqService;
    @Autowired
    private IDtrdEntEvaluationRdNrsService nrsService;
    @Autowired
    private IDtrdEntEvaluationRdJobService jobService;
    @Autowired
    private IDtrdEntEvaluationRdMmpiService mmpiService;
    @Autowired
    private IDtrdEntEvaluationRdPersonalityService personalityService;
    @Autowired
    private IDtrdEntEvaluationRdPsychologyService psychologyService;
    @Autowired
    private IDtrdEntEvaluationRdRetinopathyService retinopathyService;
    @Autowired
    private IDtrdEntEvaluationRdNephropathyService nephropathyService;
    @Autowired
    private IDtrdEntEvaluationRdNeuropathyService neuropathyService;
    @Autowired
    private IDtrdEntEvaluationRdDiabeticFootService diabeticFootService;
    @Autowired
    private IDtrdEntEvaluationRdSleepService sleepService;
    @Autowired
    private IDtrdEntEvaluationRdCdmsesService cdmsesService;
    @Autowired
    private IDtrdEntEvaluationRdDcpService dcpService;
    @Autowired
    private IDtrdEntEvaluationRdAdknowlService adknowlService;


    @Override
    public List<EvaluationInfo> getEvaluationInfoList(Integer patientId) {
        LambdaQueryWrapper<DtrdEntRdEvaluation> evaluationQueryWrapper = Wrappers.lambdaQuery(DtrdEntRdEvaluation.class)
                .eq(DtrdEntRdEvaluation::getIsDel, 0);
        List<DtrdEntRdEvaluation> evaluationPoList = this.list(evaluationQueryWrapper);
        List<EvaluationInfo> evaluationInfoList = new ArrayList<>(evaluationPoList.size());
        if (!evaluationPoList.isEmpty()){
            evaluationInfoList = evaluationPoList.stream()
                    .map(po -> new EvaluationInfo().parseFromPo(po))
                    .collect(Collectors.toList());
        }
        evaluationInfoList.forEach(evaluationInfo -> {
            Integer dataId = evaluationInfo.getDataId();
            Constant.Evaluation evaluation = Constant.Evaluation.valueOf(dataId);
            switch (evaluation){
                case SDSCA:
                    int sdscaCount = sdscaService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdSdsca.class)
                            .eq(DtrdEntEvaluationRdSdsca::getPatientId, patientId));
                    evaluationInfo.setCount(sdscaCount);
                    break;
                case CDMSES:
                    int cdmsesCount = cdmsesService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdCdmses.class)
                            .eq(DtrdEntEvaluationRdCdmses::getPatientId, patientId));
                    evaluationInfo.setCount(cdmsesCount);
                    break;
                case DCP:
                    int dcpCount = dcpService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdDcp.class)
                            .eq(DtrdEntEvaluationRdDcp::getPatientId, patientId));
                    evaluationInfo.setCount(dcpCount);
                    break;
                case ADKnowl:
                    int adknowlCount = adknowlService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdAdknowl.class)
                            .eq(DtrdEntEvaluationRdAdknowl::getPatientId, patientId));
                    evaluationInfo.setCount(adknowlCount);
                    break;
                case MMAS8:
                    int mmas8Count = mmas8Service.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdMmas8.class)
                            .eq(DtrdEntEvaluationRdMmas8::getPatientId, patientId));
                    evaluationInfo.setCount(mmas8Count);
                    break;
                case BMQ:
                    int bmqCount = bmqService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdBmq.class)
                            .eq(DtrdEntEvaluationRdBmq::getPatientId, patientId));
                    evaluationInfo.setCount(bmqCount);
                    break;
                case DIABETES:
                    int diabetesCount = diabetesService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdDiabetes.class)
                            .eq(DtrdEntEvaluationRdDiabetes::getPatientId, patientId));
                    evaluationInfo.setCount(diabetesCount);
                    break;
                case CVD:
                    int angiocardiopathyCount = angiocardiopathyService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdAngiocardiopathy.class)
                            .eq(DtrdEntEvaluationRdAngiocardiopathy::getPatientId, patientId));
                    evaluationInfo.setCount(angiocardiopathyCount);
                    break;
                case SAS:
                    int sasCount = sasService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdSas.class)
                            .eq(DtrdEntEvaluationRdSas::getPatientId, patientId));
                    evaluationInfo.setCount(sasCount);
                    break;
                case SDS:
                    int sdsCount = sdsService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdSds.class)
                            .eq(DtrdEntEvaluationRdSds::getPatientId, patientId));
                    evaluationInfo.setCount(sdsCount);
                    break;
                case PF:
                    int personalityCount = personalityService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdPersonality.class)
                            .eq(DtrdEntEvaluationRdPersonality::getPatientId, patientId));
                    evaluationInfo.setCount(personalityCount);
                    break;
                case JOB:
                    int jobCount = jobService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdJob.class)
                            .eq(DtrdEntEvaluationRdJob::getPatientId, patientId));
                    evaluationInfo.setCount(jobCount);
                    break;
                case MMPI:
                    int mmpiCount = mmpiService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdMmpi.class)
                            .eq(DtrdEntEvaluationRdMmpi::getPatientId, patientId));
                    evaluationInfo.setCount(mmpiCount);
                    break;
                case PSQI:
                    int sleepCount = sleepService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdSleep.class)
                            .eq(DtrdEntEvaluationRdSleep::getPatientId, patientId));
                    evaluationInfo.setCount(sleepCount);
                    break;
                case SCL:
                    int sclCount = psychologyService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdPsychology.class)
                            .eq(DtrdEntEvaluationRdPsychology::getPatientId, patientId));
                    evaluationInfo.setCount(sclCount);
                    break;
                case HAPPY:
                    int happyCount = happyService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdHappy.class)
                            .eq(DtrdEntEvaluationRdHappy::getPatientId, patientId));
                    evaluationInfo.setCount(happyCount);
                    break;
                case PARQ:
                    int parqCount = parqService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdParq.class)
                            .eq(DtrdEntEvaluationRdParq::getPatientId, patientId));
                    evaluationInfo.setCount(parqCount);
                    break;
                case NRS:
                    int nrsCount = nrsService.count(Wrappers.lambdaQuery(DtrdEntEvaluationRdNrs.class)
                            .eq(DtrdEntEvaluationRdNrs::getPatientId, patientId));
                    evaluationInfo.setCount(nrsCount);
                    break;
                default:
                    break;
            }
        });
        return evaluationInfoList;
    }

    @Override
    public PatientEvaluationInfo getLatestPatientEvaluationInfo(Integer patientId) {
        PatientEvaluationInfo info = new PatientEvaluationInfo();
        AngiocardiopathyInfo angiocardiopathyInfoLatest = angiocardiopathyService.getAngiocardiopathyInfoLatest(patientId);
        if (angiocardiopathyInfoLatest.getCreateTime() != null) {
            info.setAngiocardiopathyInfo(angiocardiopathyInfoLatest);
            info.setAngiocardiopathyTime(DateUtils.formatDate(angiocardiopathyInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        BmqInfo bmqInfoLatest = bmqService.getBMQInfoLatest(patientId);
        if (bmqInfoLatest.getCreateTime() != null) {
            info.setBmqInfo(bmqInfoLatest);
            info.setBmqTime(DateUtils.formatDate(bmqInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        DiabetesInfo diabetesInfoLatest = diabetesService.getDiabetesInfoLatest(patientId);
        if (diabetesInfoLatest.getCreateTime() != null) {
            info.setDiabetesInfo(diabetesInfoLatest);
            info.setDiabetesTime(DateUtils.formatDate(diabetesInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        HappyInfo happyInfoLatest = happyService.getHappyInfoLatest(patientId);
        if (happyInfoLatest.getCreateTime() != null) {
            info.setHappyInfo(happyInfoLatest);
            info.setHappyTime(DateUtils.formatDate(happyInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        JobInfo jobInfoLatest = jobService.getJobInfoLatest(patientId);
        if (jobInfoLatest.getCreateTime() != null) {
            info.setJobInfo(jobInfoLatest);
            info.setJobTime(DateUtils.formatDate(jobInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        Mmas8Info mmas8InfoLatest = mmas8Service.getMMAS8InfoLatest(patientId);
        if (mmas8InfoLatest.getCreateTime() != null) {
            info.setMmas8Info(mmas8InfoLatest);
            info.setMmas8Time(DateUtils.formatDate(mmas8InfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        MmpiDetail mmpiInfoLatest = mmpiService.getLatestMmpi(patientId);
        if (mmpiInfoLatest != null) {
            info.setMmpiInfo(mmpiInfoLatest);
            info.setMmpiTime(DateUtils.formatDate(mmpiInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        PersonalityInfo personalityInfoLatest = personalityService.getPersonalityInfoLatest(patientId);
        if (personalityInfoLatest.getCreateTime() != null) {
            info.setPersonalityInfo(personalityInfoLatest);
            info.setPersonalityTime(DateUtils.formatDate(personalityInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        PsychologyInfo psychologyInfoLatest = psychologyService.getPsychologyInfoLatest(patientId);
        if (psychologyInfoLatest.getCreateTime() != null) {
            info.setPsychologyInfo(psychologyInfoLatest);
            info.setPsychologyTime(DateUtils.formatDate(psychologyInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        SasInfo sasInfoLatest = sasService.getSasInfoLatest(patientId);
        if (sasInfoLatest.getCreateTime() != null) {
            info.setSasInfo(sasInfoLatest);
            info.setSasTime(DateUtils.formatDate(sasInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        SdscaInfo sdscaInfoLatest = sdscaService.getSdscaInfoLatest(patientId);
        if (sdscaInfoLatest.getCreateTime() != null) {
            info.setSdscaInfo(sdscaInfoLatest);
            info.setSdscaTime(DateUtils.formatDate(sdscaInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        SdsInfo sdsInfo = sdsService.getSasInfoLatest(patientId);
        if (sdsInfo.getCreateTime() != null) {
            info.setSdsInfo(sdsInfo);
            info.setSdsTime(DateUtils.formatDate(sdsInfo.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        SleepInfo sleepInfoLatest = sleepService.getSleepInfoLatest(patientId);
        if (sleepInfoLatest.getCreateTime() != null) {
            info.setSleepInfo(sleepInfoLatest);
            info.setSleepTime(DateUtils.formatDate(sleepInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        CdmsesDetail cdmsesLatest = cdmsesService.getCdmsesLatest(patientId);
        if (cdmsesLatest != null) {
            info.setCdmsesInfo(cdmsesLatest);
            info.setCdmsesTime(DateUtils.formatDate(sleepInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        AdknowlDetail adknowlLatest = adknowlService.getAdknowlLatest(patientId);
        if (adknowlLatest != null) {
            info.setAdknowlInfo(adknowlLatest);
            info.setAdknowlTime(DateUtils.formatDate(adknowlLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        DcpDetail dcpLatest = dcpService.getDcpLatest(patientId);
        if (dcpLatest != null) {
            info.setDcpInfo(dcpLatest);
            info.setDcpTime(DateUtils.formatDate(dcpLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        DiseaseEvaluationInfo diabeticFootInfo = diabeticFootService.getDiabeticFootInfo(patientId);
        if (diabeticFootInfo.getCreateTime() != null) {
            info.setDiabetesTime(DateUtils.formatDate(diabeticFootInfo.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
            info.setDiabeticFootInfo(diabeticFootInfo);
        }
        DiseaseEvaluationInfo retinopathyInfoLatest = retinopathyService.getRetinopathyInfoLatest(patientId);
        if (retinopathyInfoLatest.getCreateTime() != null) {
            info.setRetinopathyInfo(retinopathyInfoLatest);
            info.setRetinopathyTime(DateUtils.formatDate(retinopathyInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        DiseaseEvaluationInfo nephropathyInfoLatest = nephropathyService.getNephropathyInfoLatest(patientId);
        if (nephropathyInfoLatest.getCreateTime() != null) {
            info.setNephropathyInfo(nephropathyInfoLatest);
            info.setNephropathyTime(DateUtils.formatDate(nephropathyInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        DiseaseEvaluationInfo neuropathyInfoLatest = neuropathyService.getNeuropathyInfoLatest(patientId);
        if (nephropathyInfoLatest.getCreateTime() != null) {
            info.setNeuropathyInfo(neuropathyInfoLatest);
            info.setNeuropathyTime(DateUtils.formatDate(neuropathyInfoLatest.getCreateTime(), DateUtils.date_sdf.get().toPattern()));
        }
        return info;
    }

    @Override
    public TotalEvaluationReports getTotalEvaluationReports(Integer patientId, Date startDate) {
        TotalEvaluationReports reports = new TotalEvaluationReports();
        // 心血管10年风险评估
        LambdaQueryWrapper<DtrdEntEvaluationRdAngiocardiopathy> wrapper1 = Wrappers.lambdaQuery(DtrdEntEvaluationRdAngiocardiopathy.class)
                .eq(DtrdEntEvaluationRdAngiocardiopathy::getPatientId, patientId)
                .le(DtrdEntEvaluationRdAngiocardiopathy::getCreateTime, startDate)
                .orderByDesc(DtrdEntEvaluationRdAngiocardiopathy::getCreateTime)
                .last("limit 1");
        DtrdEntEvaluationRdAngiocardiopathy angiocardiopathy = angiocardiopathyService.getOne(wrapper1);
        if (angiocardiopathy != null) {
            reports.setAngiocardiopathyReport(new EvaluationReport("心血管10年风险评估").parseFromPO(angiocardiopathy));
        }
        // 糖尿病风险评估
        LambdaQueryWrapper<DtrdEntEvaluationRdDiabetes> wrapper2 = Wrappers.lambdaQuery(DtrdEntEvaluationRdDiabetes.class)
                .eq(DtrdEntEvaluationRdDiabetes::getPatientId, patientId)
                .le(DtrdEntEvaluationRdDiabetes::getCreateTime, startDate)
                .orderByDesc(DtrdEntEvaluationRdDiabetes::getCreateTime)
                .last("limit 1");
        DtrdEntEvaluationRdDiabetes diabetes = diabetesService.getOne(wrapper2);
        if (diabetes != null) {
            reports.setDiabetesReport(new EvaluationReport("糖尿病风险评估").parseFromPO(diabetes));
        }
        // 自我管理行为(SDSCA)评估
        LambdaQueryWrapper<DtrdEntEvaluationRdSdsca> wrapper3 = Wrappers.lambdaQuery(DtrdEntEvaluationRdSdsca.class)
                .eq(DtrdEntEvaluationRdSdsca::getPatientId, patientId)
                .le(DtrdEntEvaluationRdSdsca::getCreateTime, startDate)
                .orderByDesc(DtrdEntEvaluationRdSdsca::getCreateTime)
                .last("limit 1");
        DtrdEntEvaluationRdSdsca sdsca = sdscaService.getOne(wrapper3);
        if (sdsca != null) {
            reports.setSdscaReport(new EvaluationReport("自我管理行为(SDSCA)评估").parseFromPO(sdsca));
        }
        // 服药信念量表（BMQ）评估
        LambdaQueryWrapper<DtrdEntEvaluationRdBmq> wrapper4 = Wrappers.lambdaQuery(DtrdEntEvaluationRdBmq.class)
                .eq(DtrdEntEvaluationRdBmq::getPatientId, patientId)
                .le(DtrdEntEvaluationRdBmq::getCreateTime, startDate)
                .orderByDesc(DtrdEntEvaluationRdBmq::getCreateTime)
                .last("limit 1");
        DtrdEntEvaluationRdBmq bmq = bmqService.getOne(wrapper4);
        if (bmq != null) {
            reports.setBmqReport(new EvaluationReport("服药信念量表（BMQ）评估").parseFromPO(bmq));
        }
        // Morisky用药依从性问卷（MMAS-8）评估
        LambdaQueryWrapper<DtrdEntEvaluationRdMmas8> wrapper5 = Wrappers.lambdaQuery(DtrdEntEvaluationRdMmas8.class)
                .eq(DtrdEntEvaluationRdMmas8::getPatientId, patientId)
                .le(DtrdEntEvaluationRdMmas8::getCreateTime, startDate)
                .orderByDesc(DtrdEntEvaluationRdMmas8::getCreateTime)
                .last("limit 1");
        DtrdEntEvaluationRdMmas8 mmas8 = mmas8Service.getOne(wrapper5);
        if (mmas8 != null) {
            reports.setMmas8Report(new EvaluationReport("Morisky用药依从性问卷（MMAS-8）评估").parseFromPO(mmas8));
        }
        // 焦虑自评（SAS）
        LambdaQueryWrapper<DtrdEntEvaluationRdSas> wrapper6 = Wrappers.lambdaQuery(DtrdEntEvaluationRdSas.class)
                .eq(DtrdEntEvaluationRdSas::getPatientId, patientId)
                .le(DtrdEntEvaluationRdSas::getCreateTime, startDate)
                .orderByDesc(DtrdEntEvaluationRdSas::getCreateTime)
                .last("limit 1");
        DtrdEntEvaluationRdSas sas = sasService.getOne(wrapper6);
        if (sas != null) {
            reports.setSasReport(new EvaluationReport("焦虑自评（SAS）").parseFromPO(sas));
        }
        // 抑郁自评（SDS）
        LambdaQueryWrapper<DtrdEntEvaluationRdSds> wrapper7 = Wrappers.lambdaQuery(DtrdEntEvaluationRdSds.class)
                .eq(DtrdEntEvaluationRdSds::getPatientId, patientId)
                .le(DtrdEntEvaluationRdSds::getCreateTime, startDate)
                .orderByDesc(DtrdEntEvaluationRdSds::getCreateTime)
                .last("limit 1");
        DtrdEntEvaluationRdSds sds = sdsService.getOne(wrapper7);
        if (sds != null) {
            reports.setSdsReport(new EvaluationReport("抑郁自评（SDS）").parseFromPO(sds));
        }
        // 马氏工作倦怠通用量表
        LambdaQueryWrapper<DtrdEntEvaluationRdJob> wrapper8 = Wrappers.lambdaQuery(DtrdEntEvaluationRdJob.class)
                .eq(DtrdEntEvaluationRdJob::getPatientId, patientId)
                .le(DtrdEntEvaluationRdJob::getCreateTime, startDate)
                .orderByDesc(DtrdEntEvaluationRdJob::getCreateTime)
                .last("limit 1");
        DtrdEntEvaluationRdJob job = jobService.getOne(wrapper8);
        if (job != null) {
            reports.setJobReport(new EvaluationReport("马氏工作倦怠通用量表").parseFromPO(job));
        }
        // 匹兹堡睡眠质量指数（PSQI）
        LambdaQueryWrapper<DtrdEntEvaluationRdSleep> wrapper9 = Wrappers.lambdaQuery(DtrdEntEvaluationRdSleep.class)
                .eq(DtrdEntEvaluationRdSleep::getPatientId, patientId)
                .le(DtrdEntEvaluationRdSleep::getCreateTime, startDate)
                .orderByDesc(DtrdEntEvaluationRdSleep::getCreateTime)
                .last("limit 1");
        DtrdEntEvaluationRdSleep sleep = sleepService.getOne(wrapper9);
        if (sleep != null) {
            reports.setSleepReport(new EvaluationReport("匹兹堡睡眠质量指数（PSQI）").parseFromPO(sleep));
        }
        // 总体幸福感测试
        LambdaQueryWrapper<DtrdEntEvaluationRdHappy> wrapper10 = Wrappers.lambdaQuery(DtrdEntEvaluationRdHappy.class)
                .eq(DtrdEntEvaluationRdHappy::getPatientId, patientId)
                .le(DtrdEntEvaluationRdHappy::getCreateTime, startDate)
                .orderByDesc(DtrdEntEvaluationRdHappy::getCreateTime)
                .last("limit 1");
        DtrdEntEvaluationRdHappy happy = happyService.getOne(wrapper10);
        if (happy != null) {
            reports.setHappyReport(new EvaluationReport("总体幸福感测试").parseFromPO(happy));
        }
        return reports;
    }


}
